// 1.4.1 运算符-位运算符
/**
 * 算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C++ 内置了丰富的运算符，并提供了以下类型的运算符：
* 
* 算术运算符
* 关系运算符
* 逻辑运算符
* 位运算符
* 赋值运算符
* 杂项运算符
* 本章将逐一介绍算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符和其他运算符。
 *
 * 
 * 位运算符
位运算符作用于位，并逐位执行操作。&、 | 和 ^ 的真值表如下所示：

p 	q	  p & q	  p | q	  p ^ q
0	  0	    0	      0	      0
0	  1	    0	      1	      1
1	  1	    1	      1	      0
1	  0	    0	      1	      1
假设如果 A = 60，且 B = 13，现在以二进制格式表示，它们如下所示：

A = 0011 1100

B = 0000 1101

-----------------

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A  = 1100 0011

下表显示了 C++ 支持的位运算符。假设变量 A 的值为 60，变量 B 的值为 13，则：

运算符  &	
描述  按位与操作，按二进制位进行"与"运算。运算规则：
0&0=0;   
0&1=0;    
1&0=0;     
1&1=1;
实例   (A & B) 将得到 12，即为 0000 1100


运算符  |	
描述  按位或运算符，按二进制位进行"或"运算。运算规则：
0|0=0;   
0|1=1;   
1|0=1;    
1|1=1;	
实例   (A | B) 将得到 61，即为 0011 1101


运算符  ^	
描述  异或运算符，按二进制位进行"异或"运算。运算规则：
0^0=0;   
0^1=1;   
1^0=1;  
1^1=0;	
实例   (A ^ B) 将得到 49，即为 0011 0001


运算符  ~	
描述  取反运算符，按二进制位进行"取反"运算；跟反码有区别，负数的反码符号位不变，取反每一位都边。运算规则：
~1=-2;  0000 0000 0000 0000 0000 0000 0000 0001 => 1111 1111 1111 1111 1111 1111 1111 1110
~0=-1;  0000 0000 0000 0000 0000 0000 0000 0000 => 1111 1111 1111 1111 1111 1111 1111 1111	
~-3=2; 1111 1111 1111 1111 1111 1111 1111 1101 => 0000 0000 0000 0000 0000 0000 0000 0010
实例   (~A ) 将得到 -61，即为 1100 0011，一个有符号二进制数的补码形式。

运算符  <<	
描述  二进制左移运算符。将一个运算对象的各二进制位全部左移若干位（左边的二进制位丢弃，右边补0）。
实例   A << 2 将得到 240，即为 1111 0000
      -3 << 2 ; 1111 1111 1111 1111 1111 1111 1111 1101 => 1111 1111 1111 1111 1111 1111 1111 0100，即为 -12

运算符  >>	
描述  二进制右移运算符。将一个数的各二进制位全部右移若干位，正数左补0，负数左补1，右边丢弃。
实例  A >> 2 将得到 15，即为 0000 1111
     -3 >> 2 ; 1111 1111 1111 1111 1111 1111 1111 1101 => 1111 1111 1111 1111 1111 1111 1111 1111; 即为 -1
 * 
*/

#include <iostream>

int main(void)
{
  // unsigned int a = 60;
  int a = 60; //  60 == 0000 0000 0000 0000 0000 0000 0011 1100
  // unsigned int b = 13;
  int b = 13; //  13 == 0000 0000 0000 0000 0000 0000 0000 1101
  
  int d = -13;// -13 == 1111 1111 1111 1111 1111 1111 1111 0011 
  int c = 0;
  c = a & b; // 12 = 0000 0000 0000 0000 0000 0000 0000 1100, 按位与运算
  std::cout << "a & b:\t\t" << c << '\n';
  c = a & d; //   48 =  0000 0000 0000 0000 0000 0000 0011 0000
  std::cout << "a & d:\t\t" << c << '\n';

  c = a | b; // 61 = 0011 1101
  std::cout << "a | b:\t\t" << c << '\n';
  c = a ^ b; // 49 = 0011 0001
  std::cout << "a ^ b:\t\t" << c << '\n';
  c = ~a; // -61 = 1100 0011
  std::cout << "~a:\t\t" << c << '\n';
  std::cout << "~-3:\t\t" << ~-3 << '\n';
  c = a << 2; // 240 = 1111 0000
  std::cout << "a << 2:\t\t" << c << '\n';
  std::cout << "-3 << 2:\t" << (-3 << 2) << '\n';
  c = a >> 2; // 15 = 0000 1111
  std::cout << "a >> 2:\t\t" << c << '\n';
  std::cout << "-3 >> 2:\t" << (-3 >> 2) << '\n';

  printf("----------end-----------\n");
  return 0;
}